package model;

import model.Battle;
import model.Server;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;
import model.User;
import controller.Waiting;
import view.server.Decode;

public class Attendant implements Runnable {

    private Server server;
    private Socket socket;
    private ObjectInputStream in;
    private ObjectOutputStream out;
    private boolean initialized;
    private boolean running;
    private Thread thread;
    private User user;
    private Waiting waiting;

    public Attendant(Server server, Socket socket, ObjectInputStream in, ObjectOutputStream out, User user) throws Exception {
        this.server = server;
        this.socket = socket;
        this.initialized = false;
        this.running = false;
        this.user = user;
        open(in, out);
    }

    private void open(ObjectInputStream in, ObjectOutputStream out) throws Exception {
        try {
            this.in = in;
            this.out = out;
            initialized = true;
        } //try
        catch (Exception e) {
            close();
            throw e;
        } //catch
    }

    private void close() {
        if (user != null) {
            server.removeUser(user);
            server.removeAtendente(this);
        }
        if (in != null) {
            try {
                in.close();
            } catch (Exception e) {
                server.sendToConsole(e.getMessage());
            }
        } //if
        if (out != null) {
            try {
                out.close();
            } catch (Exception e) {
                server.sendToConsole(e.getMessage());
            }
        } //if
        try {
            socket.close();
        } catch (Exception e) {
            server.sendToConsole(e.getMessage());
        }
        in = null;
        out = null;
        socket = null;
        initialized = false;
        running = false;
        thread = null;
        server.notifyAllClients();
        Battle b = server.getBattle(this);
        if (b!=null){
            if (b.isBattling(this)){
                server.getBattle(this).timeout(this);
                server.removeBattle(server.getBattle(this));
            }
        }
    }
    
    public synchronized void send(Object objeto) {
            try {
                out.writeObject(objeto);
                out.flush();
                out.reset();
            } catch (IOException ex) {
                server.sendToConsole("Erro ao enviar msg");
                Logger.getLogger(Attendant.class.getName()).log(Level.SEVERE, null, ex);
                close();
            }
        }	

    public void start() {
        if (!initialized || running) {
            return;
        } //if
        running = true;
        thread = new Thread(this);
        thread.start();
    } //method

    public void stop() throws Exception {
        running = false;
        if (thread != null) {
            thread.join();
        } //if       
    } //method

    @Override
    public void run() {
        Decode dec;
        while (running) {
            try {
                socket.setSoTimeout(2500);
                Object inputServer = in.readObject();
                if (inputServer == null) {
                    break;
                }
                dec = new Decode(server, this, inputServer);
                //dec.run(server, this, mailman);
            } // Try 
            catch (SocketException e) {
                server.sendToConsole(this.getUser().getName() + " fechou de forma inesperada, encerrarando conexão...");
                //Logger.getLogger(Attendant.class.getName()).log(Level.SEVERE, null, e);
                break;
            } catch (SocketTimeoutException e) {
                //ignorar
            } catch (IllegalArgumentException e) {
                //Logger.getLogger(Attendant.class.getName()).log(Level.SEVERE, null, e);
                //server.sendToConsole(e.getMessage());
            } catch (Exception e) {
                //Logger.getLogger(Attendant.class.getName()).log(Level.SEVERE, null, e);
                server.sendToConsole(this.getUser().getName() + " fechou de forma inesperada, encerrarando conexão... ");
                break;
            }

        } // While
        server.sendToConsole("Encerrando Conexão");
        close();


    } //method

    public User getUser() {
        return user;
    } // method

    public Waiting getWaiting() {
        return waiting;
    }

    public void setWaiting(Waiting waiting) {
        this.waiting = waiting;
    }

} // class
